﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GcmpUiViewInterface.h"
#include "GcmpApiDeclaration.h"
#include "WeakReferenceable.h"

namespace gcmp
{

    class ElementId;
    class IDocument;
    class IUiView;
    class IUiDocument;
    class IUiViewEvent;
    class IUiDocumentEvent;
    class IUiDocumentCloseStrategy;
    class IUiViewParent;

/// \brief Ui文档视图管理器
FINAL_INTERFACE class GCMP_UI_VIEW_INTERFACE_EXPORT IUiDocumentViewManager : public gcmp::WeakReferenceable
{
    DEFINE_CAST_BASE(gcmp::IUiDocumentViewManager);
public:
    /// \brief 获取Ui文档视图管理器
    ///
    /// \return Ui文档视图管理器指针
    static IUiDocumentViewManager* Get();

public:
    /// \brief 析构函数
    virtual ~IUiDocumentViewManager() = 0;

    /// \brief 获取当前Ui视图
    ///
    /// \return 当前Ui视图指针
    virtual IUiView* GetCurrentUiView() = 0;

    /// \brief 获取当前Ui文档
    ///
    /// \return 当前Ui文档指针
    virtual IUiDocument*  GetCurrentUiDocument() = 0;

    /// \brief 创建或者打开Ui视图，该Ui视图没有共享ModelView。
    /// 如果传入的ModelView已经有Ui视图与之对应，则返回该Ui视图，否则创建新的Ui视图并返回
    /// 同时该接口会把返回的IUiView，设置为当前窗口并最大化
    /// 注意：请勿在Action中调用该方法！ 若需要在Action中创建视图，请使用gcmp::ActionBase::PostRequest()！！
    /// \param uiDocId Ui文档的id
    /// \param modelViewId 模型视图的id
    /// \return 创建的Ui视图指针
    GCMP_OBSOLETE_API(2020/12/01, IUiDocumentViewManager::CreateUiViewWithoutSharingModelView(int uiDocId, const ElementId& modelViewId, const std::wstring& uiViewTag, IUiViewParent* pViewParent))
        virtual IUiView* CreateUiViewWithoutSharingModelView(int uiDocId, const ElementId& modelViewId, IUiViewParent* pViewParent) = 0;

    /// \brief 创建Ui视图，该Ui视图没有共享ModelView。
    /// 注意：请勿在Action中调用该方法！ 若需要在Action中创建视图，请使用gcmp::ActionBase::PostRequest()！！
    /// \param uiDocId Ui文档的id
    /// \param modelViewId 模型视图的id
    /// \param uiViewTag Ui视图标识符，默认输入空字符串即可，
    ///                 只有当UiView和另外一个UiView的Document名字、ModelView类型、ModelView名字完全相同时，才需要为UiView设置一个唯一的标识符用于区分，
    ///                 此时若不唯一将会报错并且创建失败
    /// \return 创建的Ui视图指针
    virtual IUiView* CreateUiViewWithoutSharingModelView(int uiDocId, const ElementId& modelViewId, const std::wstring& uiViewTag, IUiViewParent* pViewParent) = 0;

    /// \brief 创建Ui视图，该Ui视图共享ModelView
    /// 该方法始终创建新的Ui视图并返回
    /// 同时该接口会把返回的IUiView，设置为当前窗口并最大化
    /// 注意：请勿在Action中调用该方法！ 若需要在Action中创建视图，请使用gcmp::ActionBase::PostRequest()！！
    /// \param uiDocId Ui文档的id
    /// \param modelViewId 模型视图的id
    /// \return 创建的Ui视图指针
    GCMP_OBSOLETE_API(2020/12/01, IUiDocumentViewManager::CreateUiViewWithSharingModelView(int uiDocId, const ElementId& modelViewId, const std::wstring& uiViewTag, IUiViewParent* pViewParent))
        virtual IUiView* CreateUiViewWithSharingModelView(int uiDocId, const ElementId& modelViewId, IUiViewParent* pViewParent) = 0;

    /// \brief 创建Ui视图，该Ui视图共享ModelView
    /// 注意：请勿在Action中调用该方法！ 若需要在Action中创建视图，请使用gcmp::ActionBase::PostRequest()！！
    /// \param uiDocId Ui文档的id
    /// \param modelViewId 模型视图的id
    /// \param uiViewTag Ui视图标识符，默认输入空字符串即可，
    ///                 只有当UiView和另外一个UiView的Document名字、ModelView类型、ModelView名字完全相同时，才需要为UiView设置一个唯一的标识符用于区分，
    ///                 此时若不唯一将会报错并且创建失败
    /// \return 创建的Ui视图指针
    virtual IUiView* CreateUiViewWithSharingModelView(int uiDocId, const ElementId& modelViewId, const std::wstring& uiViewTag, IUiViewParent* pViewParent) = 0;

    /// \brief 激活Ui视图
    ///
    /// 根据传入的ModelView，打开一个新窗口，同时将其设置为当前窗口。
    /// 注意：请勿在Action中调用该方法！ 若需要在Action中激活视图，请参照gcmp::ActionBase::PostRequest()的实现，或联系咖啡豆组
    /// 注意：此接口只允许日志使用！！！
    /// \param docName 文档的名字
    /// \param viewType 视图类型
    /// \param modelViewName 模型视图的名字
    /// \param isUiViewActivatedProgrammactially 表示调用时机是否为Ui事件回调，若是则传false，否则传true，非Ui框架相关代码的调用，都传true
    /// \return 激活成功返回true，否则返回false
    GCMP_OBSOLETE_API(2020/12/01, IUiDocumentViewManager::ActivateUiView(const std::wstring& documentName, const std::wstring& modelViewType, const std::wstring& modelViewName, const std::wstring& uiViewTag, bool isUiViewActivatedProgrammactially))
        virtual bool ActivateUiView(const std::wstring& docName, const std::wstring& viewType, const std::wstring& modelViewName, bool isUiViewActivatedProgrammactially) = 0;

    /// \brief 激活Ui视图
    ///
    /// 根据传入的ModelView，打开一个新窗口，同时将其设置为当前窗口。
    /// 注意：请勿在Action中调用该方法！ 若需要在Action中激活视图，请参照gcmp::ActionBase::PostRequest()的实现，或联系咖啡豆组
    /// 注意：此接口只允许日志使用！！！
    /// \param documentName 文档的名字
    /// \param modelViewType 视图类型
    /// \param modelViewName 模型视图的名字
    /// \param uiViewTag Ui视图标识符
    /// \param isUiViewActivatedProgrammactially 表示调用时机是否为Ui事件回调，若是则传false，否则传true，非Ui框架相关代码的调用，都传true
    /// \return 激活成功返回true，否则返回false
    virtual bool ActivateUiView(const std::wstring& documentName, const std::wstring& modelViewType, const std::wstring& modelViewName, const std::wstring& uiViewTag, bool isUiViewActivatedProgrammactially) = 0;


    /// \brief 激活Ui视图
    ///
    /// \param pUiView 要激活的UiView指针，不允许为空，否则报错
    /// \param isUiViewActivatedProgrammactially 表示调用时机是否为Ui事件回调，若是则传false，否则传true，非Ui框架相关代码的调用，都传true
    /// \return 激活成功返回true，否则返回false
    virtual bool ActivateUiView(IUiView *pUiView, bool isUiViewActivatedProgrammactially) = 0;

    /// \brief 关闭Ui视图
    ///
    /// 注意：请勿在Action中调用该方法！ 若需要在Action中激活视图，请参照gcmp::ActionBase::PostRequest()的实现，或联系咖啡豆组
    /// \param pUIView 要关闭的Ui视图的指针
    /// \param closeReason 关闭视图的原因
    /// \return 关闭成功返回true，否则返回false
    virtual bool CloseUiView(IUiView* pUIView) = 0;

    /// \brief 关闭Ui视图
    ///
    /// 注意：请勿在Action中调用该方法！ 若需要在Action中激活视图，请参照gcmp::ActionBase::PostRequest()的实现，或联系咖啡豆组
    /// \param uiDocId Ui文档的id
    /// \param viewType 视图类型
    /// \param modelViewName 模型视图的名字
    /// \param closeReason 关闭视图的原因
    /// \return 关闭成功返回true，否则返回false
    GCMP_OBSOLETE_API(2020/12/01, IUiDocumentViewManager::CloseUiViewByName(const std::wstring& documentName, const std::wstring& modelViewType, const std::wstring& modelViewName, const std::wstring& uiViewTag))
        virtual bool CloseUiViewByName(int uiDocId, const std::wstring& viewType, const std::wstring& modelViewName) = 0;

    /// \brief 关闭Ui视图
    ///
    /// 注意：请勿在Action中调用该方法！ 若需要在Action中激活视图，请参照gcmp::ActionBase::PostRequest()的实现，或联系咖啡豆组
    /// \param documentName 文档的名字
    /// \param modelViewType 视图类型
    /// \param modelViewName 模型视图的名字
    /// \param uiViewTag Ui视图标识符
    /// \return 关闭成功返回true，否则返回false
    virtual bool CloseUiViewByName(const std::wstring& documentName, const std::wstring& modelViewType, const std::wstring& modelViewName, const std::wstring& uiViewTag) = 0;

    /// \brief Ui视图是否处于可见状态
    /// 不可见的Ui视图，不能响应子窗口平铺、子窗口层叠、子窗口最大化、子窗口最小化等子窗口行为
    ///
    /// \param pUIView Ui视图的指针
    /// \return 若UiView视图当前是可见的，则返回true；否则返回false
    virtual bool IsUiViewVisible(IUiView* pUiView) const = 0;

    /// \brief 设置Ui视图的可见状态
    /// 不可见的Ui视图，不能响应子窗口平铺、子窗口层叠、子窗口最大化、子窗口最小化等子窗口行为
    ///
    /// \param pUiView 要隐藏或显示的Ui视图的指针
    /// \param visible 是否可见
    /// \return 操作成功返回true，否则返回false
    virtual bool SetUiViewVisible(IUiView* pUiView, bool visible) = 0;

    /// \brief 获取Ui视图
    ///
    /// \param uiViewId 要获取的Ui视图的id
    /// \return Ui视图的指针
    virtual IUiView* GetUiViewByRuntimeId(int uiViewId) = 0;

    /// \brief 创建Ui文档
    ///
    /// \param pDoc Db文档的指针
    /// \return 创建的Ui文档的指针
    virtual IUiDocument* CreateUiDocument(IDocument* pDoc) = 0;

    /// \brief 激活Ui文档
    ///
    /// \param uiDocId Ui文档的id
    /// \return 激活成功返回true， 否则返回false
    GCMP_OBSOLETE_API(2021/01/01, IUiDocumentViewManager::ActivateUiDocument(int uiDocId, int uiViewId))
        virtual bool ActivateUiDocument(int uiDocId) = 0;

    /// \brief 激活Ui文档
    ///
    /// \param uiDocId Ui文档的id
    /// \param uiViewId Ui视图的id，传递无效(-1)或者非UiDoc的Id，默认取第一个添加视图
    /// \return 激活成功返回true， 否则返回false
    virtual bool ActivateUiDocument(int uiDocId, int uiViewId) = 0;

    /// \brief 关闭Ui文档以及对应的Db文档
    ///
    /// \param uiDocId Ui文档的id
    /// \return 关闭成功返回true， 否则返回false
    virtual bool CloseDocument(int uiDocId) = 0;

    /// \brief 获取所有的Ui文档
    ///
    /// \return 所有Ui文档指针
    virtual std::vector<IUiDocument*> GetAllUiDocuments() = 0;

    /// \brief 根据id获取Ui文档
    ///
    /// \param uiDocId Ui文档的id
    /// \return Ui文档的指针
    virtual IUiDocument* GetUiDocumentByRuntimeId(int uiDocId) = 0;

    /// \brief 根据名字获取Ui文档
    ///
    /// \param docName Ui文档的名字
    /// \return Ui文档的指针
    virtual IUiDocument* GetUiDocumentByName(const std::wstring& docName) = 0;

    /// \brief 获取视图中处理UI事件的UiEvent对象指针。
    /// 
    /// \return 返回视图中处理UI事件的UiEvent对象指针。
    virtual IUiViewEvent* GetUiViewEvent() = 0;

    /// \brief 获取文档中处理UI事件的UiEvent对象指针。
    /// 
    /// \return 返回文档中处理UI事件的UiEvent对象指针。
    virtual IUiDocumentEvent* GetUiDocumentEvent() = 0;

    /// \brief 添加UiDocument关闭策略并放到队列头部优先执行。
    ///
    /// 允许外部定制UiDocument关闭策略，外部定制策略的执行优先于内部的关闭行为。如文档被修改过，则会调用关闭策略。
    /// 内部关闭行为执行顺序：
    ///     1. 如处于在位编辑模式，执行相关逻辑并判断是否能关闭。
    ///     2. 执行文件保存相关逻辑。
    /// \param opUiDocumentCloseStrategy 定制的UiDocument关闭策略
    /// \return 是否添加成功
    /// \see IUiDocumentCloseStrategy
    virtual bool InsertUiDocumentCloseStrategyAtHead(OwnerPtr<IUiDocumentCloseStrategy> opUiDocumentCloseStrategy) = 0;

    /// \brief 按执行顺序获取所有的UiDocument关闭策略。
    ///
    /// \return IUiDocumentCloseStrategy * UiDocument关闭策略
    virtual std::vector<IUiDocumentCloseStrategy *> GetUiDocumentCloseStrategies() = 0;
     
    /// \brief 设置默认action的命令id(当所有Action退出之后启动的工具）
    ///
    /// gcmp有默认的命令，设置之后会替换gcmp默认命令，每个新创建的IUiView的默认命令为defaultActionCommandId，设置之前已创建的IUiView不受影响
    /// 如果某个IUiView的命令与此不同，可以用IUiView上的接口SetDefaultActionCommand进行设置
    /// \param defaultActionCommandId 默认action的命令id
    /// \return true表示成功， false表示失败
    virtual bool SetUiViewDefaultActionCommandId(const std::wstring& defaultActionCommandId) = 0;

    /// \brief 获取默认action的命令id
    ///
    /// \return 返回默认action的命令id
    virtual std::wstring  GetUiViewDefaultActionCommandId() const = 0;

    /// \brief 获取是否可关闭UiDocument
    ///
    /// \return true 表示可以，false表示不可以
    virtual bool CanUiDocumentClose(int uiDocumentId) const = 0;

    /// \brief 设置打开文档后的回调函数，可以做一些界面初始化等工作
    ///
    /// \param callbackFunction 回调函数
    virtual void RegisterDocumentOpenCallback(std::function<void(gcmp::IDocument*)> callbackFunction) = 0;

    /// \brief 获取打开文档后的回调函数
    ///
    /// \return 打开文档后的回调函数
    virtual std::function<void(gcmp::IDocument*)> GetDocumentOpenCallback() const = 0;

    /// \brief 清除本地保存的ModelView对应的UiView上次关闭时状态（相机参数）
    /// 注意：目前该接口清理的是本地配置文件，非文档内的内容，乃不可逆操作，暂不需要开启事务
    /// \param uiDocId Ui文档的id
    /// \param modelViewId 模型视图的id
    /// \return true表示清除成功， false表示清除失败
    virtual bool ClearViewStateConfigByModelViewId(int uiDocId, const ElementId& modelViewId) = 0;
};

}   // end namespace gcmp

